2 <!DOCTYPE HTML PUBLIC 
"-//W3C//DTD HTML 4.01//EN"> 
   5         <link type=
"text/css" rel=
"stylesheet" href=
"style.css" /> 
  12             <img style=
"border:none" alt=
"Redis Documentation" src=
"redis.png"> 
  16             <div id=
"pagecontent"> 
  18 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. --> 
  19 <b>RedisEventLibrary: Contents
</b><br>  <a href=
"#Redis Event Library">Redis Event Library
</a><br>    <a href=
"#Event Loop Initialization">Event Loop Initialization
</a><br>      <a href=
"#aeCreateEventLoop">aeCreateEventLoop
</a><br>      <a href=
"#aeCreateTimeEvent">aeCreateTimeEvent
</a><br>      <a href=
"#aeCreateFileEvent">aeCreateFileEvent
</a><br>    <a href=
"#Event Loop Processing">Event Loop Processing
</a><br>      <a href=
"#aeProcessEvents">aeProcessEvents
</a><br>      <a href=
"#processTimeEvents">processTimeEvents
</a> 
  22                 <h1 class=
"wikiname">RedisEventLibrary
</h1> 
  29                     #sidebar 
<a href=
"RedisInternals.html">RedisInternals
</a><h1><a name=
"Redis Event Library">Redis Event Library
</a></h1>Redis implements its own event library. The event library is implemented in 
<b>ae.c
</b>.
<br/><br/>The best way to understand how the Redis event library works is to understand how Redis uses it.
<h2><a name=
"Event Loop Initialization">Event Loop Initialization
</a></h2> 
  30 <code name=
"code" class=
"python">initServer
</code> function defined in 
<b>redis.c
</b> initializes the numerous fields of the 
<code name=
"code" class=
"python">redisServer
</code> structure variable. One such field is the Redis event loop 
<code name=
"code" class=
"python">el
</code>:
<br/><br/><pre class=
"codeblock python" name=
"code">  
  32 </pre><code name=
"code" class=
"python">initServer
</code> initializes 
<code name=
"code" class=
"python">server.el
</code> field by calling 
<code name=
"code" class=
"python">aeCreateEventLoop
</code> defined in 
<b>ae.c
</b>. The definition of 
<code name=
"code" class=
"python">aeEventLoop
</code> is below:
 
  33 <pre class=
"codeblock python python" name=
"code"> 
  34 typedef struct aeEventLoop 
 
  37     long long timeEventNextId;
 
  38     aeFileEvent events[AE_SETSIZE]; /* Registered events */
 
  39     aeFiredEvent fired[AE_SETSIZE]; /* Fired events */
 
  40     aeTimeEvent *timeEventHead;
 
  42     void *apidata; /* This is used for polling API specific data */
 
  43     aeBeforeSleepProc *beforesleep;
 
  45 </pre><h3><a name=
"aeCreateEventLoop">aeCreateEventLoop
</a></h3><code name=
"code" class=
"python">aeCreateEventLoop
</code> first mallocs aeEventLoop structure then calls ae_epoll.c:aeApiCreate
<code name=
"code" class=
"python">.
 
  47 </code>aeApiCreate
<code name=
"code" class=
"python"> mallocs 
</code>aeApiState
<code name=
"code" class=
"python"> that has two fields - 
</code>epfd
<code name=
"code" class=
"python"> that holds the epoll file descriptor returned by a call from [http://man.cx/epoll_create%
282%
29 epoll_create] and 
</code>events
<code name=
"code" class=
"python"> that is of type 
</code>struct epoll_event
<code name=
"code" class=
"python"> define by the Linux epoll library. The use of the 
</code>events
<code name=
"code" class=
"python"> field will be  described later.
 
  49 Next is 'ae.c:aeCreateTimeEvent
</code>. But before that 
<code name=
"code" class=
"python">initServer
</code> call 
<code name=
"code" class=
"python">anet.c:anetTcpServer
</code> that creates and returns a 
<i>listening descriptor
</i>. The descriptor is listens to 
<b>port 
6379</b> by default. The returned  
<i>listening descriptor
</i> is stored in 
<code name=
"code" class=
"python">server.fd
</code> field.
<h3><a name=
"aeCreateTimeEvent">aeCreateTimeEvent
</a></h3><code name=
"code" class=
"python">aeCreateTimeEvent
</code> accepts the following as parameters:
<br/><br/><ul><li> eventLoop: This is 
<code name=
"code" class=
"python">server.el
</code> in 
<b>redis.c
</b></li><li> milliseconds: The number of milliseconds from the curent time after which the timer expires.
</li><li> proc: Function pointer. Stores the address of the function that has to be called after the timer expires.
</li><li> clientData: Mostly NULL.
</li><li> finalizerProc: Pointer to the function that has to be called before the timed event is removed from the list of timed events.
</li></ul> 
  50 <code name=
"code" class=
"python">initServer
</code> calls 
<code name=
"code" class=
"python">aeCreateTimeEvent
</code> to add a timed event to 
<code name=
"code" class=
"python">timeEventHead
</code> field of 
<code name=
"code" class=
"python">server.el
</code>. 
<code name=
"code" class=
"python">timeEventHead
</code> is a pointer to a list of such timed events. The call to 
<code name=
"code" class=
"python">aeCreateTimeEvent
</code> from 
<code name=
"code" class=
"python">redis.c:initServer
</code> function is given below:
<br/><br/><pre class=
"codeblock python python python" name=
"code"> 
  51 aeCreateTimeEvent(server.el /*eventLoop*/, 
1 /*milliseconds*/, serverCron /*proc*/, NULL /*clientData*/, NULL /*finalizerProc*/);
 
  52 </pre><code name=
"code" class=
"python">redis.c:serverCron
</code> performs many operations that helps keep Redis running properly.
<h3><a name=
"aeCreateFileEvent">aeCreateFileEvent
</a></h3>The essence of 
<code name=
"code" class=
"python">aeCreateFileEvent
</code> function is to execute 
<a href=
"http://man.cx/epoll_ctl" target=
"_blank">epoll_ctl
</a> system call which adds a watch for 
<code name=
"code" class=
"python">EPOLLIN
</code> event on the 
<i>listening descriptor
</i> create by 
<code name=
"code" class=
"python">anetTcpServer
</code> and associate it with the epoll descriptor created by a call to 
<code name=
"code" class=
"python">aeCreateEventLoop
</code>. 
<br/><br/>Following is an explanation of what precisely 
<code name=
"code" class=
"python">aeCreateFileEvent
</code> does when called from 
<code name=
"code" class=
"python">redis.c:initServer
</code>.
<br/><br/><code name=
"code" class=
"python">initServer
</code> passes the following arguments to 
<code name=
"code" class=
"python">aeCreateFileEvent
</code>:
 
  53 <ul><li> server.el: The event loop created by 
<code name=
"code" class=
"python">aeCreateEventLoop
</code>. The epoll descriptor is got from server.el. 
</li><li> server.fd: The 
<i>listening descriptor
</i> that also serves as an index to access the relevant file event structure from the 
<code name=
"code" class=
"python">eventLoop-
>events
</code> table and store extra information like the callback function.
</li><li> AE_READABLE: Signifies that server.fd has to be watched for EPOLLIN event.
</li><li> acceptHandler: The function that has to be executed when the event being watched for is ready. This function pointer is stored in 
<code name=
"code" class=
"python">eventLoop-
>events[server.fd]-
>rfileProc
</code>. 
</li></ul> 
  54 This completes the initialization of Redis event loop.
<h2><a name=
"Event Loop Processing">Event Loop Processing
</a></h2><code name=
"code" class=
"python">ae.c:aeMain
</code> called from 
<code name=
"code" class=
"python">redis.c:main
</code> does the job of processing the event loop that is initialized in the previous phase.
<br/><br/><code name=
"code" class=
"python">ae.c:aeMain
</code> calls 
<code name=
"code" class=
"python">ae.c:aeProcessEvents
</code> in a while loop that processes pending time and file events.
<h3><a name=
"aeProcessEvents">aeProcessEvents
</a></h3><code name=
"code" class=
"python">ae.c:aeProcessEvents
</code> looks for the time event that will be pending in the smallest amount of time by calling 
<code name=
"code" class=
"python">ae.c:aeSearchNearestTimer
</code> on the event loop. In our case there is only one timer event in the event loop that was created by 
<code name=
"code" class=
"python">ae.c:aeCreateTimeEvent
</code>. 
<br/><br/>Remember, that timer event created by 
<code name=
"code" class=
"python">aeCreateTimeEvent
</code> has by now probably elapsed because it had a expiry time of one millisecond. Since, the timer has already expired the seconds and microseconds fields of the 
<code name=
"code" class=
"python">tvp
</code> timeval structure variable is initialized to zero. 
<br/><br/>The 
<code name=
"code" class=
"python">tvp
</code> structure variable along with the event loop variable is passed to 
<code name=
"code" class=
"python">ae_epoll.c:aeApiPoll
</code>.
<br/><br/><code name=
"code" class=
"python">aeApiPoll
</code> functions does a 
<a href=
"http://man.cx/epoll_wait" target=
"_blank">epoll_wait
</a> on the epoll descriptor and populates the 
<code name=
"code" class=
"python">eventLoop-
>fired
</code> table with the details:
 
  55 <ul><li> fd: The descriptor that is now ready to do a read/write operation depending on the mask value. The 
</li><li> mask: The read/write event that can now be performed on the corresponding descriptor.
</li></ul> 
  56 <code name=
"code" class=
"python">aeApiPoll
</code> returns the number of such file events ready for operation. Now to put things in context, if any client has requested for a connection then aeApiPoll would have noticed it and populated the 
<code name=
"code" class=
"python">eventLoop-
>fired
</code> table with an entry of the descriptor being the 
<i>listening descriptor
</i> and mask being 
<code name=
"code" class=
"python">AE_READABLE
</code>.
<br/><br/>Now, 
<code name=
"code" class=
"python">aeProcessEvents
</code> calls the 
<code name=
"code" class=
"python">redis.c:acceptHandler
</code> registered as the callback. 
<code name=
"code" class=
"python">acceptHandler
</code> executes [
<a href=
"http://man.cx/accept(2" target=
"_blank">http://man.cx/accept(
2</a>) accept] on the 
<i>listening descriptor
</i> returning a 
<i>connected descriptor
</i> with the client. 
<code name=
"code" class=
"python">redis.c:createClient
</code> adds a file event on the 
<i>connected descriptor
</i> through a call to 
<code name=
"code" class=
"python">ae.c:aeCreateFileEvent
</code> like below:
<br/><br/><pre class=
"codeblock python python python python" name=
"code"> 
  57     if (aeCreateFileEvent(server.el, c-
>fd, AE_READABLE,
 
  58         readQueryFromClient, c) == AE_ERR) {
 
  62 </pre><code name=
"code" class=
"python">c
</code> is the 
<code name=
"code" class=
"python">redisClient
</code> structure variable and 
<code name=
"code" class=
"python">c-
>fd
</code> is the connected descriptor.
<br/><br/>Next the 
<code name=
"code" class=
"python">ae.c:aeProcessEvent
</code> calls 
<code name=
"code" class=
"python">ae.c:processTimeEvents
</code><h3><a name=
"processTimeEvents">processTimeEvents
</a></h3><code name=
"code" class=
"python">ae.processTimeEvents
</code> iterates over list of time events starting at 
<code name=
"code" class=
"python">eventLoop-
>timeEventHead
</code>.
<br/><br/>For every timed event that has elapsed 
<code name=
"code" class=
"python">processTimeEvents
</code> calls the registered callback. In this case it calls the only timed event callback registered, that is, 
<code name=
"code" class=
"python">redis.c:serverCron
</code>. The callback returns the time in milliseconds after which the callback must be called again. This change is recorded via a call to 
<code name=
"code" class=
"python">ae.c:aeAddMilliSeconds
</code> and will be handled on the next iteration of 
<code name=
"code" class=
"python">ae.c:aeMain
</code> while loop.
<br/><br/>That's all.