Saturday, November 23, 2013

Extracting formatted input using stringstream

Description: The following program shows how to extract formatted input from a stringstream object.


#include <iostream>
#include <fstream>
#include <sstream>

/*
  Extracting formatted input using stringstream >> operator.

  While extracting input, if there are any errors it could set eofbit, badbit or failbit in its internal error state falgs.

  Then it checks its exception mask to decide wheter to throw an exception or not.

  For example if failbit is set in exception mask and  failbit was set during extraction then >> operation would

  throw an ios_base::failure exception.
*/

using namespace std;
void getexceptionmask(const stringstream& ss)
{

ios_base::iostate exceptionmask = ss.exceptions();


if(exceptionmask & ifstream::badbit)
{
cout << "badbit is set. If an operation on sstream causes this bit to be set, an exception of type ios_base::failure would be thrown.\n" ;
}

if(exceptionmask & ifstream::failbit)
{
cout << "failbit is set. If an operation on sstream causes this bit to be set, an exception of type ios_base::failure would be thrown.\n" ;
}
}

void checkerrorstate(const stringstream& ss)
{

if(ss.bad())
{
cout << "Bad bit is set. We failed to read an integer" << endl;
}

if(ss.fail())
{
cout << "Fail bit or Bad bit is set. We failed to read an integer" << endl;
}
}

int main(int argc, char** argv)
{

stringstream ss;

cout << "Printing the default exception mask." << endl;

getexceptionmask(ss);

cout << "Printing after setting badbit and failbit exception mask." << endl;

ss.exceptions(ifstream::badbit | ifstream::failbit);

getexceptionmask(ss);

cout << "Printing after clearing the exception mask." << endl;

/*  
*if exception mask  has only goodbit (which is zero) streams  do not throw exceptions due to error state flags being set
*/
ss.exceptions(ifstream::goodbit);

getexceptionmask(ss);

int n;

cout << "Trying to read an integer when the stream is empty." << endl;

ss >> n;

cout << "Checking if any of the error bits were set." << endl;

checkerrorstate(ss);

/*
* clearing the errot state.
*/

ss.clear();

cout << "Printing exception mask after setting fail bit." << endl;

ss.exceptions(ifstream::failbit);

getexceptionmask(ss);

cout << "Now again trying to read an integer. We should get an exception now." << endl;

ss >> n;

}

Output:

Printing the default exception mask.
Printing after setting badbit and failbit exception mask.
badbit is set. If an operation on sstream causes this bit to be set, an exception of type ios_base::failure would be thrown.
failbit is set. If an operation on sstream causes this bit to be set, an exception of type ios_base::failure would be thrown.
Printing after clearing the exception mask.
Trying to read an integer when the stream is empty.
Checking if any of the error bits were set.
Fail bit or Bad bit is set. We failed to read an integer
Printing exception mask after setting fail bit.
failbit is set. If an operation on sstream causes this bit to be set, an exception of type ios_base::failure would be thrown.
Now again trying to read an integer. We should get an exception now.
terminate called after throwing an instance of 'std::ios_base::failure'
  what():  basic_ios::clear

Aborted

Saturday, October 19, 2013

A ReadWrite implementation with preference to waiting writers.

Description:  Below is an implementation of ReadWrite using Mutex and Condition Variables with preference to waiting writers. Before a read lock is given, we check if there are any writers waiting to get write lock. Similary, when a lock is released, if a writer is waiting to get the lock , preference is given to them over readers.

RwLock.h (Header File)

#include <pthread.h>


class RwLock
{
    //nreaders = 0 , indicates no. reader/writer exists.
    //nreaders > 0, indicates one or more read lock exists.
    //nreaders=-1, indicates a write lock exists.

    int nreaders;

    int nwaitwriters;
   
    pthread_mutex_t rw_mutex;

    pthread_cond_t rw_condreader;
   
    pthread_cond_t rw_condwriter;

    public:

    RwLock();

    void getReadLock();

    void getWriteLock();

    void unLock();

    ~RwLock();

       
};


RwLock.C (Implementation)

#include "RwLock.h"

RwLock :: RwLock()
{
    nreaders = 0;

    nwaitwriters = 0;

    pthread_mutex_init(&rw_mutex, NULL);   

    pthread_cond_init(&rw_condreader, NULL);

    pthread_cond_init(&rw_condwriter, NULL);
}

void RwLock :: getReadLock()
{
    //Obtain Lock.
    pthread_mutex_lock(&rw_mutex);

    //If  a WRITER exists(nreaders = -1)wait for signal from writer.
    while(-1 == nreaders || 0 < nwaitwriters)
    {
        pthread_cond_wait(&rw_condwriter, &rw_mutex);
    }

    //increment no. of readers
    nreaders++;

    pthread_mutex_unlock(&rw_mutex);       
}


void RwLock :: getWriteLock()
{
    //Obtain Lock
    pthread_mutex_lock(&rw_mutex);

    //if nreader is != 0 it means either a reader or writer is present. wait for signal from reader/writer (do it in a loop)
    while(0 != nreaders)
    {
        //Increment no. of waiting writers.
        nwaitwriters++;

        pthread_cond_wait(&rw_condreader, &rw_mutex);
       
        //Decrement no. of waiting writers.
        nwaitwriters--;
       
    }

    //set nreader = -1 indicating a writer is present.
    nreaders = -1;

    //unlock the mutex.
    pthread_mutex_unlock(&rw_mutex);
}

void RwLock :: unLock()
{
    //Obtain Lock
    pthread_mutex_lock(&rw_mutex);

    if(0 < nreaders)
    {
        //one of the readers is done. decrement readers count.
        nreaders--;

        if(0 == nreaders)
        {
            //last reader is done.

            if(0 < nwaitwriters)
            {
                //if a writer is waiting
                pthread_cond_signal(&rw_condreader);
            }
        }
    }
    else if(-1 == nreaders)
    {
        //a writer is done. set nreaders to 0 indicating no reader/writer exists.
        nreaders = 0;

        if(0 < nwaitwriters)
        {
            //if a writer is waiting.
            pthread_cond_signal(&rw_condreader);
        }
        else
        {           
            //broadcast to any waiting readers.
            pthread_cond_broadcast(&rw_condwriter);
        }
    }

    pthread_mutex_unlock(&rw_mutex);
}

RwLock :: ~RwLock()
{
    //Destroy condition variable and mutex.
    pthread_mutex_destroy(&rw_mutex);

    pthread_cond_destroy(&rw_condreader);

    pthread_cond_destroy(&rw_condwriter);
}

Sunday, October 6, 2013

Implementation of readwrite lock using mutex and condition variables.

Description: Below is an implementation of readwrite lock using mutex and condition variables. Note that, the implementation does not give any preference to waiting writers.


RwLock.h (Header File)

#include <pthread.h>
 
class RwLock
{
    //nreaders = 0 , indicates no. reader/writer exists.
    //nreaders > 0, indicates one or more read lock exists.
    //nreaders=-1, indicates a write lock exists.

    int nreaders;
   
    pthread_mutex_t rw_mutex;

    pthread_cond_t rw_cond;

    public:

    RwLock();

    void getReadLock();

    void getWriteLock();

    void unLock();

    ~RwLock();
       
};

RwLock.C (Implementation of our  ReadWrite Lock)
#include "RwLock.h"

RwLock :: RwLock()
{
    nreaders = 0;
   
    // Initialize mutex and condition variable.
    pthread_mutex_init(&rw_mutex, NULL);   

    pthread_cond_init(&rw_cond, NULL);
}

void RwLock :: getReadLock()
{
    //Obtain Lock.
    pthread_mutex_lock(&rw_mutex);

    // If  a WRITER exists(nreaders = -1)wait for signal from writer.
    while(-1 == nreaders)
    {
        pthread_cond_wait(&rw_cond, &rw_mutex);
    }

    // Increment no. of reader
    nreaders++;

    //Unlock the mutex.
    pthread_mutex_unlock(&rw_mutex);       
}


void RwLock :: getWriteLock()
{
    //Obtain Lock
    pthread_mutex_lock(&rw_mutex);

    // If nreader is != 0 it means either a reader or writer is present. wait for signal from reader/writer (do it in a loop)
    while(0 != nreaders)
    {
        pthread_cond_wait(&rw_cond, &rw_mutex);
    }

    // Set nreader = -1 indicating a writer is present.
    nreaders = -1;

    // Unlock the mutex.
    pthread_mutex_unlock(&rw_mutex);
}

void RwLock :: unLock()
{
    // Obtain Lock.
    pthread_mutex_lock(&rw_mutex);

    if(0 < nreaders)
    {
        // One of the readers is done. decrement readers count.
        nreaders--;

        if(0 == nreaders)
        {
            // Last reader is done.
            pthread_cond_broadcast(&rw_cond);
        }
    }
    else if(-1 == nreaders)
    {
        // A writer is done. set nreaders to 0 indicating no reader/writer exists.
        nreaders = 0;
        pthread_cond_broadcast(&rw_cond);
    }
    // Unlock the mutex.
    pthread_mutex_unlock(&rw_mutex);
}

RwLock :: ~RwLock()
{
    // Destroy condition variable and mutex.
    pthread_mutex_destroy(&rw_mutex);

    pthread_cond_destroy(&rw_cond);
}

Below is a sample program that uses this implementation and output obtained.


#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<iostream>

#include "RwLock.h"

using namespace std;

RwLock rwlock;

void* reader(void* arg)
{
    cout << "Obtaining read lock." << endl;

    rwlock.getReadLock();
   
    cout << "Obtained read lock." << endl;

    sleep(5);

    cout << "Releasing read lock." << endl;

    rwlock.unLock();

    cout << "Released read lock." << endl;   
}


void* writer(void* arg)
{
    cout << "Obtaining write lock." << endl;

    rwlock.getWriteLock();
   
    cout << "Obtained write lock." << endl;

    sleep(4);

    cout << "Releasing write lock." << endl;

    rwlock.unLock();

    cout << "Released write lock." << endl;   
}

int main(int argc, char** argv)
{
    pthread_t r1,r2,r3,w1,w2;

    int res;

    cout << endl;   

    res = pthread_create(&r1, NULL, reader, NULL);

    if(0 != res)
    {
        cout << "Failed to start thread." << endl;
        exit(1);
    }
           
    res = pthread_create(&r2, NULL, reader, NULL);

    if(0 != res)
    {
        cout << "Failed to start thread." << endl;
        exit(1);
    }           

    sleep(1);

    res = pthread_create(&w1, NULL, writer, NULL);

    if(0 != res)
    {
        cout << "Failed to start thread." << endl;
        exit(1);
    }   

    res = pthread_create(&w2, NULL, writer, NULL);

    if(0 != res)
    {
        cout << "Failed to start thread." << endl;
        exit(1);
    }   
    pthread_exit(NULL);       
}

Output:
Obtaining read lock.
Obtained read lock. 
Obtaining read lock.
Obtained read lock.            /*Two read locks obtained*/
Obtaining write lock.
Obtaining write lock.         /*Two threads waiting for write lock*/
Releasing read lock.
Released read lock.
Releasing read lock.
Released read lock.         /*Two read locks are released*/
Obtained write lock.       
Releasing write lock.
Released write lock.       /*A thread first gets write lock and releases it*/  
Obtained write lock.      /*Second thread gets the write lock*/
Releasing write lock.
Released write lock.

Saturday, September 28, 2013

MinHeap implementation.

Description:  The below program is an implementation of MinHeap. While creating the MinHeap, youneed to specify the max. no of elements it can hold. It provides two operations insert() and getMinimum().


HeaderFile:

#include <exception>

using namespace std;

#define HEAP_EMPTY 1

#define HEAP_FULL 2

class MinHeapException : public exception
{
    private:
    int code;

    public:
    MinHeapException(int n) : code(n)
    {

    }

    const char* what() const throw()
    {
        switch(code)
        {
            case HEAP_EMPTY:
                return "Heap is empty.";

            case HEAP_FULL:
                return "Heap is full.";
        }
    }   
};


class MinHeap
{
    private:
   
    const int capacity;
    int size;
    int* ptr;

    public:

    MinHeap(int n);
       
    void insert(int n) throw(MinHeapException);

    int getMinimum() throw(MinHeapException);

    void display();

    ~MinHeap();   
};

Implementation of our MinHeap:

#include "MinHeap.h"
#include <iostream>

using namespace std;

MinHeap :: MinHeap(int n) : capacity(n), size(0), ptr(new int[n+1])
{
       
}


void MinHeap :: insert(int n) throw(MinHeapException)
{
    /*
     * If the heap is already full, throw a exception.
     */   

    if(size == capacity)
    {
        throw MinHeapException(HEAP_FULL);
    }

    int hole;

    /*Increment the size of heap*/
    size++;

     /*The hole points  to the last position.
     *Move up the hole, still we get suitable position. i.e the parent of the hole
     *must be greater than the new no. that we want to insert in the hole.
     */
    for(hole = size ; hole > 1 && ptr[hole/2] > n; hole = hole/2)
    {
        ptr[hole] = ptr[hole/2];
    }

    ptr[hole] = n;
}


int MinHeap :: getMinimum() throw(MinHeapException)
{

    /*
     *If the heap is empty throw an exception.
     */   
    if(0 == size)
    {
        throw MinHeapException(HEAP_EMPTY);   
    }

    int firstelement = ptr[1];

    int lastelement = ptr[size];

    int hole;
    int smallelement;

    /*
     * Decrement the size of heap.
     */

    size--;

    /*
     * Intially the hole is created in the first element.
     * The hole is moved down till we get to a poistion where the childrens are greater than the last element.
     */ 
    for(hole = 1;  hole <= size/2; hole = smallelement)
    {
       
        if(2*hole+1 <= size)
        {
            /*Ther are two childs*/
            if(lastelement < ptr[2*hole] && lastelement < ptr[2*hole+1])
            {
                /*Bot the children are greater than the lastelement. So last element can be placed here*/                break;
            }
           
            /*Find to which subtree the hole should be moved*/
            smallelement = ptr[2*hole] < ptr[2*hole+1] ? 2*hole : 2*hole+1;

        }
        else
        {       
            /*There is one child*/
            if(lastelement < ptr[2*hole])
            {
                /*The child is greater than the lastelement*/
                break;
            }
            smallelement = 2*hole;
        }

        /*Move the samllest children into hole. hole is moved done to smallest children  posistion*/            ptr[hole] = ptr[smallelement];   
    }
   
    /*Replace the hole with the last element*/
    ptr[hole] = lastelement;

    /*Return the first element*/
    return firstelement;

}

void MinHeap :: display()
{
    int i;

    for(i=1; i <= size; i++)
    {
        cout << ptr[i] << " ";
    }
    cout << endl;   
}

MinHeap :: ~MinHeap()
{
    delete [] ptr;
}


int main(int argc, char** argv)
{

    try
    {

            MinHeap heap(11);

            heap.insert(13);
            heap.insert(14);
            heap.insert(16);
            heap.insert(19);
            heap.insert(21);
            heap.insert(19);
            heap.insert(68);
            heap.insert(65);
            heap.insert(26);
            heap.insert(32);
            heap.insert(31);
            heap.insert(41);

            cout << "1st Minimum:" << heap.getMinimum() << endl;

            heap.display();

            cout << "2nd Minimum:" << heap.getMinimum() << endl;

            heap.display();

            cout << "3rd Minimum:" << heap.getMinimum() << endl;

            heap.display();

            cout << "4th Minimum:" << heap.getMinimum() << endl;

            heap.display();

            cout << "5th Minimum:" << heap.getMinimum() << endl;
    }
    catch(MinHeapException& e)
    {
        cout << e.what();
    }
}

Wednesday, September 25, 2013

Converting string representation of time to unix epoch time.

#include <iostream>
#include <string>
#include <time.h>
#include <stdlib.h>

using namespace std;

int main(int argc, char** argv)
{
    string s_time = "Thu, 19 Oct 2006 11:52:22 +0200";

    struct tm tm;

    /*Convert from string representation to struct tm */

    char* ptr = strptime(s_time.c_str(), "%a, %d %b %Y %T %z", &tm);

    if('\0' != *ptr)
    {
        /*A part of the string was not  processed*/
        cout << "Following part of string not processed:" << ptr  << endl;
    }

    /*Convert from struct tm to time_t structure.*/

    time_t time = mktime(&tm);

    if(-1 == time)
    {
        cout << "Failed to convert from 'struct tm' to 'time_t'" << endl;
        exit(1);
    }
    else
    {
        cout << "Given time in unix time stamp:" << time << endl;
    }

    exit(0);
}

Output:
Given time in unix time stamp:1161238942

Saturday, September 7, 2013

Example Apache module for reading request body.

Description: 
An apache c module, that reads the request body from a PUT/POST request body, saves it on the disk  and returns HTTP 201 (Created) status code if successful and returns the URI which the user can use to retrieve back the contents in "Location" response header and the name of the file in which the contents were saved in the response body.



Generating template for the module using 'apxs' tool:

  Using the -g option of 'apxs' tool, we can generate a basic template of a module and add our logic to it.

    #> /usr/local/apache2/bin/apxs -g -n putfile
    Creating [DIR]  putfile
    Creating [FILE] putfile/Makefile
    Creating [FILE] putfile/modules.mk
    Creating [FILE] putfile/mod_putfile.c
    Creating [FILE] putfile/.deps

  The above command creates a template for a module named 'putfile' and a Makefile to compile.
 
Module source code:
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"
#include "ap_config.h"

#define BLOCKSIZE 4096

const char* documentRoot = "/usr/local/apache2/htdocs/";

int readAndWriteData(request_rec *r, int fd)
{
     int ret = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);

     if(OK == ret && ap_should_client_block(r))
     {
          char* buffer = (char*)apr_pcalloc(r->pool, BLOCKSIZE);

          int len;

          while((len=ap_get_client_block(r, buffer, BLOCKSIZE)) > 0)
          {
                if(-1 == write(fd, buffer, len))
                        return -1;
          }

          return (-1 == len ? -1 : 0);
     }

     return -1;

}


static int putfile_handler(request_rec *r)
{

    /*
    * For each request, apache decides based on the 'SetHanlder' and 'AddHandler'
   * directive, the module which would handle the request and populates the request_rec::handler
     * field with the name of the module.
     *
   * A well behaving mo1dule should check if the value of this field matches with its name and
     * process the request only if it does. 
     */
    if (strcmp(r->handler, "putfile")) {
        return DECLINED;
    }

    /*
     * This module supports only 'PUT'/'POST' requests.
     */
    if(M_PUT != r->method_number && M_POST != r->method_number)
    {
        return DECLINED;
    }


    char fileName[200] = {'\0'};

    struct timeval tv;

    gettimeofday(&tv, NULL);

    sprintf(fileName, "%sputfile/%ld.%ld", documentRoot, tv.tv_sec, tv.tv_usec);


    int fd = creat(fileName, 0644);

    if(-1 == fd)
    {
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    close(fd);

    if(0 != ret)
    {
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    r->content_type = "text/plain";

    /* Set response HTTP status */
    r->status = HTTP_CREATED;

    apr_table_add(r->headers_out, "Location", fileName + strlen(documentRoot));

    ap_rputs(fileName + strlen(documentRoot), r);

    return OK;
}

static void putfile_register_hooks(apr_pool_t *p)
{
    ap_hook_handler(putfile_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA putfile_module = {
    STANDARD20_MODULE_STUFF,
    NULL,                  /* create per-dir    config structures */
    NULL,                  /* merge  per-dir    config structures */
    NULL,                  /* create per-server config structures */
    NULL,                  /* merge  per-server config structures */
    NULL,                  /* table of config file commands       */
    putfile_register_hooks  /* register hooks                      */
};

Compiling and Installing the module:
Running the below command would compile the module and copy the shared library created to the modules directory (/usr/local/apache2/modules)

#> /usr/local/apache2/bin/apxs -c -i  mod_putfile.c

Apache configuration:

LoadModule putfile_module     modules/mod_putfile.so

<Location /putfile>
  SetHandler putfile
</Location>


Testing the module:
i) Create a sample file to send in the request.

#> echo "Sample Module" > input_file
 
#> cat input_file
Sample Module

ii) Send a PUT request.
#> curl -T ./input_file  -D header http://127.0.0.1/putfile/
putfile/1378555086.385071

#> cat header
HTTP/1.1 100 Continue

HTTP/1.1 201 Created
Date: Sat, 07 Sep 2013 11:58:06 GMT
Server: Apache/2.2.22 (Unix) mod_ssl/2.2.22 OpenSSL/1.0.0e
Location: putfile/1378555086.385071
Content-Length: 25
Content-Type: text/plain

iii) Retrieve the file from the server.

#>wget http://127.0.0.1/putfile/1378555086.385071
--2013-09-07 17:29:19--  http://127.0.0.1/putfile/1378555086.385071
Connecting to 127.0.0.1:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 14 [text/plain]
Saving to: `1378555086.385071'

100%[===========================================================================================================>] 14          --.-K/s   in 0s     

2013-09-07 17:29:19 (754 KB/s) - `1378555086.385071' saved [14/14]

#> cat 1378555086.385071
Sample Module

Sunday, August 25, 2013

TCP Echo Server using epoll, an example for Event Driven Server

Description: Implementation of tcp echo server using epoll. The server accepts connections from clients, reads data and echo's the same data back to the clients. All the operations accepting connections from clients, reading and writing data are done in a non-blocking manner.


server.h

/*
 * Contains definitions of constants and data structures used.
 */

#define SERVERPORT 8080

#define MAXCONN 200

#define MAXEVENTS 100

#define MAXLEN 255

struct EchoEvent
{
    int fd;
    uint32_t event;
    char data[MAXLEN];
    int length;
    int offset;

};

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include "server.h"

int epollfd;

void modifyEpollContext(int epollfd, int operation, int fd, uint32_t events, void* data)
{
    struct epoll_event server_listen_event;

    server_listen_event.events = events;

    server_listen_event.data.ptr = data;

    if(-1 == epoll_ctl(epollfd, operation, fd, &server_listen_event))
    {
        printf("Failed to add an event for socket%d Error:%s", fd, strerror(errno));
        exit(1);       
    }
   
}
void* handle(void* ptr)
{
    struct EchoEvent* echoEvent = ptr;

    if(EPOLLIN == echoEvent->event)
    {
        int n = read(echoEvent->fd, echoEvent->data, MAXLEN);
   
        if(0 == n)
        {
            /*
             * Client closed connection.
             */

            printf("\nClient closed connection.\n");
            close(echoEvent->fd);
            free(echoEvent);
        }
        else if(-1 == n)
        {
           
            close(echoEvent->fd);
            free(echoEvent);
        }
        else
        {
            echoEvent->length = n;
       
            printf("\nRead data:%s Length:%d", echoEvent->data , n);           
            printf("\nAdding write event.\n");
            /*
             * We have read the data. Add an write event so that we can
             * write data whenever the socket is ready to be written.
             */

            modifyEpollContext(epollfd, EPOLL_CTL_ADD, echoEvent->fd, EPOLLOUT, echoEvent);
        }       
   
    }
    else if(EPOLLOUT == echoEvent->event)
    {
        int ret;

         ret = write(echoEvent->fd, (echoEvent->data) + (echoEvent->offset), echoEvent->length);
       
        if( (-1 == ret && EINTR == errno) || ret < echoEvent->length)
        {
            /*
             * We either got EINTR or write only sent partial data.
             * Add an write event. We still need to write data.
             */           
   
           
            modifyEpollContext(epollfd, EPOLL_CTL_ADD, echoEvent->fd, EPOLLOUT, echoEvent);
           
            if(-1 != ret)
            {
               /*
               * The previous write wrote only partial data to the socket.
               */

                echoEvent->length = echoEvent->length - ret;
                echoEvent->offset = echoEvent->offset + ret;   
            }
           
        }
        else if(-1 == ret)
        {
           /*
            * Some other error occured.
            */
            close(echoEvent->fd);
            free(echoEvent);
        }
       
        else
        {   
       
          /*
           * The entire data was written. Add an read event,
           * to read more data from the socket.
           */
            printf("\nAdding Read Event.\n");   
            modifyEpollContext(epollfd, EPOLL_CTL_ADD, echoEvent->fd, EPOLLIN, echoEvent);
        }
    }

}


void makeSocketNonBlocking(int fd)
{
    int flags;
   
    flags = fcntl(fd, F_GETFL, NULL);

    if(-1 == flags)
    {
        printf("fcntl F_GETFL failed.%s", strerror(errno));
        exit(1);
    }

    flags |= O_NONBLOCK;

    if(-1 == fcntl(fd, F_SETFL, flags))   
    {
        printf("fcntl F_SETFL failed.%s", strerror(errno));
        exit(1);
    }       
}


int main(int argc, char** argv)
{
   
    int serverfd;

    struct sockaddr_in server_addr;

    struct sockaddr_in clientaddr;
    socklen_t clientlen = sizeof(clientaddr);

   /*
    * Create server socket. Specify the nonblocking socket option.
    *
    */   
    serverfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

    if(-1 == serverfd)
    {
        printf("Failed to create socket.%s", strerror(errno));
        exit(1);
    }   
   
    bzero(&server_addr, sizeof(server_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVERPORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
   
   /*
    * Bind the server socket to the required ip-address and port.
    *
    */

    if(-1 == bind(serverfd, (struct sockaddr*)&server_addr, sizeof(server_addr)))
    {
        printf("Failed to bind.%s", strerror(errno));
        exit(1);
    }

   /*
    * Mark the server socket has a socket that will be used to .
    * accept incoming connections.
    */
  
  if(-1 == listen(serverfd, MAXCONN))
    {
        printf("Failed to listen.%s", strerror(errno));
        exit(1);
    }

   /*
    * Create epoll context.
    */
  
 
    epollfd = epoll_create(MAXCONN);

    if(-1 == epollfd)
    {
        printf("Failed to create epoll context.%s", strerror(errno));
        exit(1);
    }

   /*
    * Create read event for server socket.
    */
  
modifyEpollContext(epollfd, EPOLL_CTL_ADD, serverfd, EPOLLIN, &serverfd);

   /*
    * Main loop that listens for event.
    */
    struct epoll_event *events = calloc(MAXEVENTS, sizeof(struct epoll_event));
    while(1)
    {
        int n = epoll_wait(epollfd, events, MAXEVENTS, -1);

        if(-1 == n)               
        {
            printf("Failed to wait.%s", strerror(errno));
            exit(1);
        }
       
        int i;
        for(i = 0; i < n; i++)
        {
            if(events[i].data.ptr == &serverfd)
            {
                if(events[i].events & EPOLLHUP || events[i].events & EPOLLERR)
                {
                  /*
                   * EPOLLHUP and EPOLLERR are always monitored.
                   */
   
                close(serverfd);
                     exit(1);
                }   

               /*
               * New client connection is available. Call accept.
               * Make connection socket non blocking.
               * Add read event for the connection socket.
               */
   
            int connfd = accept(serverfd, (struct sockaddr*)&clientaddr, &clientlen);

                if(-1 == connfd)
                {
                    printf("Accept failed.%s", strerror(errno));
                    exit(1);
                }
                else
                {
                    printf("Accepted connection.Sleeping for minute.\n");
                   
                    makeSocketNonBlocking(connfd);
               
                    sleep(60);
               
                    printf("Adding a read event\n");

                    struct EchoEvent* echoEvent = calloc(1, sizeof(struct EchoEvent));

                    echoEvent->fd = connfd;
                   
                  /*
                  * Add a read event.
                  */
      
              modifyEpollContext(epollfd, EPOLL_CTL_ADD, echoEvent->fd, EPOLLIN, echoEvent);
                }   
            }
            else
            {
                /*
                 *A event has happend for one of the connection sockets.
                 *Remove the connection socket from the epoll context.
                 * When the event is handled by handle() function ,
                 *it will add the required event to listen for this 
                 *connection socket again to epoll
                 *context
                 */   


                if(events[i].events & EPOLLHUP || events[i].events & EPOLLERR)
                {
                    struct EchoEvent* echoEvent = (struct EchoEvent*) events[i].data.ptr;
                    printf("\nClosing connection socket\n");
                    close(echoEvent->fd);
                    free(echoEvent);
                }
                else if(EPOLLIN == events[i].events)   
                {
                    struct EchoEvent* echoEvent = (struct EchoEvent*) events[i].data.ptr;
                   
                    echoEvent->event = EPOLLIN;
                  /*
                 * Delete the read event.
                 */   
          
          modifyEpollContext(epollfd, EPOLL_CTL_DEL, echoEvent->fd, 0, 0);

                    handle(echoEvent);
                }
                else if(EPOLLOUT == events[i].events)   
                {
                    struct EchoEvent* echoEvent = (struct EchoEvent*) events[i].data.ptr;
                   
                    echoEvent->event = EPOLLOUT;
                   
                    /*
                   * Delete the write event.
                   */       
               
    modifyEpollContext(epollfd, EPOLL_CTL_DEL, echoEvent->fd, 0, 0);

                    handle(echoEvent);
                }
            }
           
        }
    }

    free(events);
    exit(0);
}


/*
 *About Level Trigerred:
 * We have added an fd for event EPOLLIN and then data is available for read in fd. epoll_wait will continuously report EPOLLIN event still all data is read.
 *
 *About Edge Trigerred:
 * In the above case, epoll_wait will report only once. When it reports we have to read all data. If without reading all data if we call epoll_wait
 * it will not report again. Also lets say fd is already readable, you are adding an event EPOLLIN | EPOLLET and calling epoll_wait, it will report EP * OLLIN.
 *
 * Default behaviour is level trigerred. To enable EdgeTrigerred use EPOLLET option while adding events.
 */