Mercurial > hg > freeDiameter
view extensions/rt_redirect/redir_expiry.c @ 1268:25fad6714991
Updated copyright information
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Sat, 03 Jan 2015 02:18:08 +0800 |
parents | 82280e745a89 |
children | ab6457399be2 |
line wrap: on
line source
/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis <sdecugis@freediameter.net> * * * * Copyright (c) 2014, WIDE Project and NICT * * All rights reserved. * * * * Redistribution and use of this software in source and binary forms, with or without modification, are * * permitted provided that the following conditions are met: * * * * * Redistributions of source code must retain the above * * copyright notice, this list of conditions and the * * following disclaimer. * * * * * Redistributions in binary form must reproduce the above * * copyright notice, this list of conditions and the * * following disclaimer in the documentation and/or other * * materials provided with the distribution. * * * * * Neither the name of the WIDE Project or NICT nor the * * names of its contributors may be used to endorse or * * promote products derived from this software without * * specific prior written permission of WIDE Project and * * NICT. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *********************************************************************************************************/ #include "rt_redir.h" /* Expiration management */ /* Entries by their ascending expiration date, to accelerate the work of the expire thread */ static struct fd_list expire_list = FD_LIST_INITIALIZER(expire_list); static pthread_cond_t exp_cnd = PTHREAD_COND_INITIALIZER; pthread_mutex_t redir_exp_peer_lock = PTHREAD_MUTEX_INITIALIZER; /* The thread that handles expired entries cleanup. */ void * redir_exp_thr_fct(void * arg) { fd_log_threadname ( "Redirects/expire" ); TRACE_ENTRY( "" ); CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock), goto fatal_error ); pthread_cleanup_push( fd_cleanup_mutex, &redir_exp_peer_lock ); do { struct timespec now; struct redir_entry * first; again: /* Check if there are expiring entries available */ if (FD_IS_LIST_EMPTY(&expire_list)) { /* Just wait for a change or cancelation */ CHECK_POSIX_DO( pthread_cond_wait( &exp_cnd, &redir_exp_peer_lock ), break /* this might not pop the cleanup handler, but since we ASSERT(0), it is not the big issue... */ ); /* Restart the loop on wakeup */ goto again; } /* Get the pointer to the entry that expires first */ first = (struct redir_entry *)(expire_list.next->o); /* Get the current time */ CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), break ); /* If first session is not expired, we just wait until it happens */ if ( TS_IS_INFERIOR( &now, &first->timeout ) ) { CHECK_POSIX_DO2( pthread_cond_timedwait( &exp_cnd, &redir_exp_peer_lock, &first->timeout ), ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */, /* on other error, */ break ); /* on wakeup, loop */ goto again; } /* Now, the first entry in the list is expired; destroy it */ CHECK_FCT_DO( redir_entry_destroy( first ), break ); } while (1); pthread_cleanup_pop( 0 ); CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock), ); fatal_error: TRACE_DEBUG(INFO, "A system error occurred in redirect module! Expiry thread is terminating..."); ASSERT(0); return NULL; } /* Sets the timeout value & link in expiry list. The mutex must be held on calling */ int redir_exp_set(struct redir_entry * e, uint32_t duration) { struct fd_list * li; TRACE_ENTRY("%p %d", e, duration); CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC) && duration ); /* Unlink in case it was already set before */ fd_list_unlink(&e->exp_list); /* Get current time */ CHECK_SYS( clock_gettime(CLOCK_REALTIME, &e->timeout) ); /* Add the duration */ e->timeout.tv_sec += duration; /* now search the next element in the list */ for (li = expire_list.next; li != &expire_list; li = li->next) { struct redir_entry * n = li->o; if ( TS_IS_INFERIOR( &e->timeout, &n->timeout ) ) break; } /* Insert before this element */ fd_list_insert_before(li, &e->exp_list); /* Signal the expiry thread if needed */ if (e->exp_list.prev == &expire_list) { /* it is the first element */ CHECK_POSIX( pthread_cond_signal(&exp_cnd) ); } /* Done */ return 0; }