src/vfer_accept_queue.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 2005, 2006, Internet2
00003  * Legal conditions are in file LICENSE
00004  * (MD5 = c434f2e53b8089d8b4d0172c7ce07360).
00005  */
00006 /**
00007  * @file   vfer_accept_queue.c
00008  * @author Ivan Beschastnikh
00009  * @brief  Implements an accept queue to hold to be accepted connections from
00010  * remote clients.
00011  *
00012  * The queue size is determine by the backlog argument
00013  * to Accept_Queue_Create. The queue wraps around upon reaching the
00014  * end, so that older connection requests are overwritten if they are
00015  * not taken off the queue in time.  note that the top pointer in the
00016  * Accept_Queue structure always points to the oldest connection
00017  * request record in the queue. Once the next_free pointer wraps
00018  * around to bump against the top of the queue, the top of the queue
00019  * moves up by one (thus loosing the oldest connection request)
00020  *
00021  * Implemented with blocking in mind, the Dequeue function
00022  * blocks if the queue is empty and wakes up when something
00023  * appears in the queue
00024  *
00025  * -    05/14/06        ivan            removed locks since accept_queue access is restricted to a single thread (ControlT thread)
00026  * -    09/01/05        ivan            modified to use new packet structures
00027  * -    07/02/05        ivan            rewritten to support I2 api
00028  * -    05/26/05        ivan            created
00029  */
00030 
00031 #include "vfer_accept_queue.h"
00032 
00033 /* static void  Accept_Queue_Print      (accept_queue* ac); */
00034 
00035 /**
00036  * Creates the accept queue structure and initializes the data members.
00037  *
00038  * @param backlog the max number of connection to queue in this queue. backlog > 0
00039  *        right now there is no limit on the size of the backlog
00040  * @return
00041  *      pointer to an new accept_queue with backlog max depth on succes
00042  *      NULL on error
00043  */
00044 accept_queue* Accept_Queue_Create (int backlog) {
00045         accept_queue* ac;
00046         
00047         DEBUG_PRINT(DEBUG_ACCEPTQ, "accept_queue.c", "Accept_Queue_Create", "Entered with backlog[%d]", backlog);
00048 
00049         if (backlog <= 0) return NULL;
00050         if (! ALLOC(ac, accept_queue*, accept_queue, 1)) return NULL;
00051         
00052         ac->count = 0;
00053         ac->backlog = backlog;
00054         ac->first = NULL;
00055         ac->last = NULL;
00056         return ac;
00057 }
00058 
00059 /**
00060  * Deletes the accept queue structure.
00061  *
00062  * @param ac accept_queue pointer
00063  */
00064 void Accept_Queue_Delete (accept_queue* ac) {
00065         queued_conn *c1, *c2;
00066         DEBUG_PRINT(DEBUG_ACCEPTQ, "accept_queue.c", "Accept_Queue_Delete", "Entered");
00067         /* go through and release all the elements in the accept queue */
00068         c1 = ac->first;
00069         while (c1 != NULL) {
00070                 c2 = c1->next;
00071                 RELEASE_PACK(c1->request);
00072                 RELEASE(c1, sizeof(queued_conn));
00073                 c1 = c2;
00074         }
00075         RELEASE (ac, sizeof(accept_queue));
00076 }
00077 
00078 /**
00079  * Adds a queued connection to a queue.
00080  *
00081  * If the queue is full, then we merely wrap around and overwrite old
00082  * connections
00083  *
00084  * @param ac accept_queue pointer to which we are trying to enqueue the connection
00085  * @param fd the file descriptor of the open connection
00086  * @param sa the socke address strucutre describing the remote connection
00087  * @param request request packet associated with the new connection
00088  * @return
00089  *      0 on succes
00090  *      -1 on error
00091  */
00092 int Accept_Queue_Enqueue (accept_queue* ac, int fd, struct sockaddr sa, packet* request) 
00093 {
00094         queued_conn* qc;
00095         queued_conn* tmp;
00096 
00097         DEBUG_PRINT(DEBUG_ACCEPTQ, "accept_queue.c", "Accept_Queue_Enqueue", "Enqueueing new connection fd[%d] into accept queue with size[%d]", fd, ac->count);
00098         
00099         /* this socket doesn't queue any connections */
00100         if (ac->backlog == 0) {
00101                 DEBUG_PRINT(DEBUG_ACCEPTQ, "accept_queue.c", "Accept_Queue_Enqueue", "Backlog=0 ; dropping conn fd[%d]", fd);
00102                 return 0;
00103         }
00104         
00105         if (! ALLOC(qc, queued_conn*, queued_conn, 1)) {
00106                 return -1;
00107         }
00108         
00109         qc->next        = ac->first;
00110         qc->prev        = NULL;
00111         qc->fd          = fd;
00112         qc->sa          = sa;
00113         qc->request     = request;
00114 
00115         if (ac->count == ac->backlog) { 
00116                 /* shift the whole list to the right */
00117                 if (ac->last == ac->first) {
00118                         /* i.e. ac->backlog == 1 ; note that we don't
00119                          * allow a backlog of 0.*/
00120                         if (ac->first != NULL) {
00121                                 RELEASE_PACK(ac->last->request);
00122                                 RELEASE(ac->last, sizeof(struct queued_conn));
00123                         }
00124                         ac->first = ac->last = qc;
00125                 } else {
00126                         tmp = ac->last->prev;
00127                         RELEASE_PACK(ac->last->request);
00128                         RELEASE(ac->last, sizeof(struct queued_conn));
00129                         ac->last = tmp;
00130                         ac->last->next = NULL;
00131                         ac->first->prev = qc;
00132                         ac->first = qc;
00133                 }
00134         } else {
00135                 /* add to back of queue (pointed to by ac->first) */
00136                 if (ac->count == 0)
00137                         ac->last = qc;
00138                 else
00139                         ac->first->prev = qc;
00140 
00141                 ac->first = qc;
00142                 ac->count++;
00143         }
00144         DEBUG_PRINT(DEBUG_ACCEPTQ, "accept_queue.c", "Accept_Queue_Enqueue", "New accept queue size[%d]", ac->count);
00145         return 0;
00146 } /* Accept_Queue_Enqueue() */
00147 
00148 
00149 /**
00150  * Removes and returns a queued connection from the front of the queue.
00151  *
00152  * This function does not block.
00153  *
00154  * @param ac accept queue pointer from which we dequeu
00155  * @return
00156  *      queued connection structure on success (if not empty queue)
00157  *      NULL on error (empty queue or otherwise)
00158  */
00159 queued_conn* Accept_Queue_Dequeue (accept_queue* ac) {
00160         queued_conn* saved_top;
00161         
00162         DEBUG_PRINT(DEBUG_ACCEPTQ, "accept_queue.c", "Accept_Queue_Dequeue", "Entered with accept queue size[%d]", ac->count);
00163         if (ac->count == 0) {
00164                 return NULL;
00165         }
00166 
00167         saved_top = ac->last;
00168 
00169         if (ac->count == 1) {
00170                 ac->last = ac->first = NULL;
00171         } else {
00172                 ac->last = ac->last->prev;
00173         }
00174         ac->count--;
00175         return saved_top;
00176 } /* Accept_Queue_Dequeue() */
00177 
00178 /**
00179  * Prints the accept queue forward and back. Useful as an internal
00180  * debugging tool.
00181  *
00182  * @param
00183  *      ac is an accept queue pointer
00184  */
00185 /* static void Accept_Queue_Print(accept_queue* ac) {
00186         queued_conn* qc;
00187         int i;
00188 
00189         qc = ac->first;
00190         i = 0;
00191         printf("FORWARD: \n");
00192         while (qc != NULL) {
00193                 printf("[%d] : %d\n", i, qc->fd);
00194                 i++;
00195                 qc = qc->next;
00196         }
00197 
00198         qc = ac->last;
00199         i = 0;
00200         printf("BACK: \n");
00201         while (qc != NULL) {
00202                 printf("[%d] : %d\n", i, qc->fd);
00203                 i++;
00204                 qc = qc->prev;
00205         }
00206 
00207         return;
00208 } */ /* Accept_Queue_Print() */

Generated on Tue Aug 8 16:07:17 2006 for VFER by  doxygen 1.4.7