Redis Source Analysis (20)---AE event driver

Source: Internet
Author: User
Tags epoll

Event-driven this noun appears more and more frequent, sounded very tall, today I put the REDIS internal driving model research, feeling harvest quite abundant ah. A ae.c main program, plus 4 of event-type files, lets you thoroughly figure out how Redis handles these events. In Redis's event handling, Epoll,select,kqueue and evport,evport are used and may be unfamiliar to many. The first 3 are very common events that are also present in the Libevent Event network library. In writing this event-driven model, the author also says that this is just for the simple reuse of the design of a small processing model:

/* A simple Event-driven Programming library. Originally I wrote this code
 * to the Jim's Event-loop (Jim is a TCL interpreter) but later translated
 * it in fo RM of a library for easy reuse.
 *
 AE is a simple event-driven library written by the author and transformed later to make it easier to reuse
So it's not very complicated. Before you understand the entire event-driven model, there are some defining event structures, with an event type of 2 fileevent,timeevent in total:

/* File Event structure *
	/////* The aefileevent of struct {//typedef is only for read events or 1 kinds of int mask in the Write event
    ;/* One of Ae_ (readable| Writable)
    /////Read method
    Aefileproc *rfileproc;
    Writing method
    Aefileproc *wfileproc;
    Client data
    void *clientdata;
} aefileevent;
    Vent identifier. ///
    time seconds
    long when_sec/* seconds///
    time millisecond
    long when_ms; * milliseconds///
    Time Event processing function C21/>aetimeproc *timeproc;
    The method that will be invoked when deleted is
    aeeventfinalizerproc *finalizerproc;
    Client data
    void *clientdata;
    The next structure body in the time structure
    struct aetimeevent *next;
aetimeevent;
    C34/>int mask;
} Aefiredevent;
FireEvent is only used to mark the file event to be processed.

These events all exist in a aeeventloop structure body:

/* State of the event based program *
/typedef struct AEEVENTLOOP {
	//the highest file descriptor
    int MAXFD currently created;   /* Highest file descriptor currently registered/
    int setsize; * Max number of file descriptors tracked/
    /Next Time Event ID
    long long timeeventnextid;
    time_t Lasttime;     /* Used to detect system clock skew
    ///3 event type aefileevent
    *events;/* Registered events/aefiredevent
    *f ired; /* Fired Events * *
    aetimeevent *timeeventhead;
    Event stop identifier
    int stop;
    Here is the event API data, including Epoll,select and other events
    void *apidata; * This is used the for polling API specific data */
    Aebefores Leepproc *beforesleep;
} Aeeventloop;
Within each event, a corresponding handler function is defined, and the function as a variable exists in the structure. Here's a look at the composition of some of the APIs in AE.C:

/* Prototypes * * aeeventloop *aecreateeventloop (int setsize); /* Create Aeeventloop, the number of internal fileevent and fired events is setsize/void Aedeleteeventloop (Aeeventloop *eventloop); /* Delete EventLoop, release the space of the corresponding Event/void Aestop (Aeeventloop *eventloop); /* Setting the Stop property in EventLoop is 1/int aecreatefileevent (aeeventloop *eventloop, int fd, int mask, aefileproc *proc, void * Clientdata); /* Create file event in EventLoop/void Aedeletefileevent (aeeventloop *eventloop, int fd, int mask); /* Delete File event */int aegetfileevents (aeeventloop *eventloop, int fd); According to the file descriptor ID, find out the file's properties, whether read or write event long long aecreatetimeevent (Aeeventloop *eventloop, long long milliseconds, aetimepr OC *proc, void *clientdata, Aeeventfinalizerproc *finalizerproc); /* Add a time event in EventLoop that is created at the current time plus its own incoming time */int aedeletetimeevent (Aeeventloop *eventloop, long long ID); According to the time ID, deletes the time event, involves the operation of the linked list int aeprocessevents (aeeventloop *eventloop, int flags); /* handles all types of events in EventLoop/int aewait (int fd, int mask, long long milliseconds); /* Let an event wait for/void Aemain (Aeeventloop *eventloop);
/* AE Event Execution Main program/char *aegetapiname (void); void Aesetbeforesleepproc (Aeeventloop *eventloop, Aebeforesleepproc *beforesleep); /* Call/int aegetsetsize (Aeeventloop *eventloop) every time the EventLoop event is executed and the execution starts again; /* Get the size of eventloop/int aeresizesetsize (aeeventloop *eventloop, int setsize);
 /* EventLoop Resize * *
Nothing but involved in some files, the addition of time events, modifications, etc., are within the eventloop internal changes, we look at the most important, the most core method:

/* AE Event Execution main program
/void Aemain (Aeeventloop *eventloop) {
    eventloop->stop = 0;
    If the stop flag bit in the EventLoop is not 1, call the
    if (!eventloop->stop) {
    	//each time the EventLoop event completes and then restarts execution.
        Eventloop->beforesleep!= NULL)
            eventloop->beforesleep (eventloop);
        The while loop handles all Evetloop events
        aeprocessevents (EventLoop, ae_all_events);
    }

The reason is simple, while loops, handling all types of events in EventLoop, intercepting part of Processevents () code:

 numevents = Aeapipoll (EventLoop, TVP);
            for (j = 0; J < numevents J + +) {aefileevent *fe = &eventLoop->events[eventLoop->fired[j].fd];
            int mask = eventloop->fired[j].mask;
            int FD = eventloop->fired[j].fd;

	    int rfired = 0;  /* Note the Fe->mask & mask & ... Code:maybe an already processed event removed a element that Fired and we still didn ' t * processed, so we check if the event is still valid.
                */if (Fe->mask & mask & ae_readable) {rfired = 1;
            According to the mask calculation to determine whether the AE read event, the call time of the Read processing method Fe->rfileproc (Eventloop,fd,fe->clientdata,mask); } if (Fe->mask & mask & ae_writable) {if (!rfired | | fe->wfileproc!= FE-&GT;RF
            Ileproc) Fe->wfileproc (eventloop,fd,fe->clientdata,mask);
        } processed++;
    }} 
The creation time events in AE are created on the basis of the current time;

/* Add a time event in EventLoop that is created at the current time plus the time you passed in/long long
aecreatetimeevent (Aeeventloop *eventloop, Long Long milliseconds,
        aetimeproc *proc, void *clientdata,
        aeeventfinalizerproc *finalizerproc)
{
    Long long id = eventloop->timeeventnextid++;
    Aetimeevent *te;

    Te = Zmalloc (sizeof (*te));
    if (Te = = NULL) return ae_err;
    Te->id = ID;
    Aeaddmillisecondstonow (Milliseconds,&te->when_sec,&te->when_ms);
    Te->timeproc = proc;
    Te->finalizerproc = Finalizerproc;
    Te->clientdata = Clientdata;
    The newly added head to timeevent
    te->next = eventloop->timeeventhead;
    Eventloop->timeeventhead = te;
    
    Returns the ID return ID of the newly created time event
    ;

Here's how to invoke the method in the Event API library. First of all, introduce what is Epoll,poll,select,kqueu and Evport. These are all an event model.

Model of Select Event

(1) Create a Descriptor collection (Fd_set) for the event of interest, for a descriptor, you can focus on the read (read), write, and exception (exception) events above, so you typically create three fd_set, a descriptor for collecting attention-reading events. A descriptor that collects attention to write events, and another collection of descriptors that is used to collect attention to exception events.
(2) Polling every FD in the fd_set to check if there is a corresponding incident, and if so, handle it.

The difference between poll and above is that you can reuse file descriptors, which need to poll 3 file descriptor sets for a file, and poll only need one, more efficient
Epoll is an upgraded version of poll, giving the list of descriptors to the kernel, and once an event occurs, the kernel notifies the process of the event's descriptor list, which avoids polling the entire descriptor list. The efficiency is greatly improved

Evport This appears to be relatively small, roughly meaning that evport the specific event of an object to the event port:

After understanding the principles of the 3 event models, let's look at how ae.c is invoked in Redis,

Here is the event API data, including Epoll,select and other events
    void *apidata; * This is used the for polling API specific data * *
This is the property above, in the above 4 events, corresponding to 3 files, respectively, AE_POLL.C,AE_SELECT.C, but their API structure is similar, I cite one example, epoll example, first of all have this event-specific structure:

typedef struct AEAPISTATE {
    int epfd;
    struct epoll_event *events;
} Aeapistate;
There are also template methods for common routines:

static int aeapicreate (Aeeventloop *eventloop)
static int aeapiresize (Aeeventloop *eventloop, int setsize)
static void Aeapifree (Aeeventloop *eventloop)
static int aeapiaddevent (aeeventloop *eventloop, int fd, int mask)
static void Aeapidelevent (Aeeventloop *eventloop, int fd, int delmask)
static int Aeapipoll (Aeeventloop * EventLoop, struct timeval *tvp)
static char *aeapiname (void)
At the time of creation, assign the value to the EventLoop API data:

STATE->EPFD = epoll_create (1024); /* 1024 is just a hint for the kernel/
    if (STATE->EPFD = 1) {
        zfree (state->events);
        Zfree (state);
        return-1;
    }
    Finally, the state data is assigned to the EventLoop API data
    eventloop->apidata = State;
    return 0;
When you remove the poll method of an event, it is a point of distinction for these methods:

static int Aeapipoll (Aeeventloop *eventloop, struct timeval *tvp) {
    aeapistate *state =
    eventloop->apidata; int retval, numevents = 0;

    retval = epoll_wait (state->epfd,state->events,eventloop->setsize,
            TVP? (tvp->tv_sec*1000 + tvp->tv_usec/1000):-1);
    if (retval > 0) {
.....
The poll method in the select is this:

static int Aeapipoll (Aeeventloop *eventloop, struct timeval *tvp) {
    aeapistate *state =
    eventloop->apidata; int retval, j, numevents = 0;

    memcpy (&state->_rfds,&state->rfds,sizeof (Fd_set));
    memcpy (&state->_wfds,&state->wfds,sizeof (Fd_set));

    retval = Select (eventloop->maxfd+1,
                &STATE->_RFDS,&STATE->_WFDS,NULL,TVP);
......
Finally, the operation is based on the transformation between the events in state and the EventLoop. Incoming information in the EventLoop, incoming state information, through internal processing to arrive at the end of the event results. The call is as simple as that.

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.